package cate.game.play.part;

import cate.common.table.d.GDFight;
import cate.game.attr.FightAttr;
import cate.game.play.fighter.Fighter;
import cate.game.play.fighter.HallowFighter;
import cate.game.play.fighter.HeroFighter;
import cate.game.play.fighter.PetFighter;
import cate.game.play.proce.play.PlayCtx;
import cate.game.play.support.PlayBuildContext;
import cate.game.play.util.CampAttrUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import cp.solution.util.collection.ListKit;
import cp.solution.util.collection.MapKit;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;

import java.util.*;
import java.util.stream.Collectors;

@NoteClass("战斗队伍")
public class FightTeam {

	@NoteField("队伍")
	public byte team;

	@NoteField("圣器")
	public HallowFighter hallow;

	@NoteField("副圣器")
	public HallowFighter deputyHallow;

	@NoteField(value = "队伍中的英雄",detail = "尽量用get方法获取 有些时候其实需要带上主角的 有的时候需要排除离场英雄")
	private List<HeroFighter> heros = new ArrayList<>();

	@NoteField("灵宠")
	public Map<Integer, PetFighter> pets;

	@NoteField("队伍状态")
	public FightTeamStatus status = new FightTeamStatus();

	@JsonIgnore
	public boolean isLoss() {
		for (Fighter f : getAllHero()) {
			if (f.isAlive()) {
				return false;
			}
		}
		return true;
	}

	public FightTeam() {}

	public FightTeam(byte team) {
		this.team = team;
	}

	public static FightTeam build(PlayBuildContext ctx, byte team, PlaySide ps) {
		FightTeam fightTeam = new FightTeam(team);
		fightTeam.addHeros(ps.buildHeroFighters(ctx));
		fightTeam.setHallow(ps.buildHallowFighter(false), false);
		fightTeam.setHallow(ps.buildHallowFighter(true), true);
		if (ps.pets != null) {
			for (Map.Entry<Integer, BattlePet> entry : ps.pets.entrySet()) {
				fightTeam.setPet(entry.getKey(), entry.getValue().buildFighter());
			}
		}
		return fightTeam;
	}

	public List<HallowFighter> getHallows() {
		List<HallowFighter> hallows = new ArrayList<>();
		if (hallow != null) {
			hallows.add(hallow);
		}
		if (deputyHallow != null) {
			hallows.add(deputyHallow);
		}
		return hallows;
	}

	public List<PetFighter> getPets() {
		List<PetFighter> petList = new ArrayList<>();
		if (pets != null) {
			petList.addAll(pets.values());
		}
		return petList;
	}

	/**
	 * 添加英雄
	 * @param fighter
	 */
	private void addHero(HeroFighter fighter) {
		if (fighter == null) {
			return;
		}
		fighter.fightTeam = this;
		fighter.team = team;
		heros.add(fighter);
	}

	/**
	 * 添加英雄
	 * @param fighters
	 */
	public void addHeros(List<HeroFighter> fighters){
		for (HeroFighter fighter : fighters) {
			addHero(fighter);
		}
	}

	public void setHallow(HallowFighter hallow, boolean deputy) {
		if (hallow == null) {
			return;
		}
		hallow.fightTeam = this;
		hallow.team = team;
		if (deputy) {
			this.deputyHallow = hallow;
		} else {
			this.hallow = hallow;
		}
	}

	public void setPet(int pos, PetFighter pet) {
		pet.fightTeam = this;
		pet.team = team;
		if (pets == null) {
			pets = new HashMap<>();
		}
		pets.put(pos, pet);
	}

	public void addTeamBuff(int teamBuff) {
		status.teamBuffs.add(teamBuff);
	}

	public List<Integer> getTeamBuffs() {
		return status.teamBuffs;
	}

	public void addTeamAttr(FightAttr attr){
		status.teamAttr.add(attr);
	}

	public FightAttr getTeamAttr(){
		return status.teamAttr;
	}

	public void beforeFight(PlayCtx playCtx) {
		CampAttrUtil.handle(playCtx.config, this);
		for (HallowFighter hallow : getHallows()) {
			addTeamAttr(hallow.teamAttr);
		}
		for (Fighter fighter : getFixFighters()) {
			fighter.attr.beforeFight(playCtx);
			fighter.skill.beforeFight(playCtx);
			fighter.buff.beforeFight();
			if (fighter.type == GDFight.Fighter.HERO) {
				fighter.attr.addAttr(getTeamAttr());
			}
		}
	}


	public void onFightBegin(PlayCtx play) {
		for (Fighter fighter : getFixFighters()) {
			play.reg(fighter);
		}
		status.beginTotalSpeed = getAllHero().stream().mapToDouble(f -> f.attr.total().speedTotal()).sum();
	}

	/**
	 * 获取固定的战斗单位(主角和英雄，不包括召唤兽)
	 * @return
	 */
	@JsonIgnore
	public List<Fighter> getFixFighters() {
		List<Fighter> fighters = new ArrayList<>();
		if (hallow != null) {
			fighters.add(hallow);
		}
		if (deputyHallow != null) {
			fighters.add(deputyHallow);
		}
		if (pets != null) {
			fighters.addAll(pets.values());
		}
		fighters.addAll(heros);
		return fighters;
	}

	public HeroFighter findHeroByPid(int pid) {
		for (HeroFighter fighter : getAllHero()) {
			if (fighter.getPid() == pid) {
				return fighter;
			}
		}
		return null;
	}

	public HeroFighter findHeroByTid(int tid) {
		for (HeroFighter fighter : heros) {
			if (fighter.heroTid == tid) {
				return fighter;
			}
		}
		return null;
	}

	public HeroFighter findHeroByProtoId(int protoId) {
		for (HeroFighter fighter : heros) {
			if (fighter.protoId == protoId) {
				return fighter;
			}
		}
		return null;
	}

	/**
	 * 获取场地上可选择的战斗单位（英雄和召唤物）
	 * @return
	 */
	@JsonIgnore
	public List<Fighter> getAreaFighters(){
		List<Fighter> fighters = new ArrayList<>();
		fighters.addAll(getHeroAvailable());
		return fighters;
	}

	/**
	 * 获取场地上所有的战斗单位（英雄和召唤物）
	 * @return
	 */
	public List<Fighter> getAllAreaFighters(){
		List<Fighter> fighters = new ArrayList<>();
		fighters.addAll(getAllHero());
		return fighters;
	}



	/**
	 * 获取可以作为目标的英雄单位
	 * @return
	 */
	private List<HeroFighter> getHeroAvailable() {
		return heros.stream().filter(fighter -> !fighter.status.isGhost()).collect(Collectors.toList());
	}


	/**
	 * 获取所有友方单位（不包括主角）
	 * @param fighter
	 * @return
	 */
	public List<Fighter> getFriends(Fighter fighter){
		return getFriends(fighter, false);
	}

	/**
	 * 获取所有友方单位（不包括主角）
	 * @param fighter
	 * @return
	 */
	public List<Fighter> getFriends(Fighter fighter, boolean shuffle) {
		List<Fighter> fighters = getAreaFighters().stream().filter(a -> a.getPid() != fighter.getPid()).collect(Collectors.toList());
		if (shuffle) {
			Collections.shuffle(fighters);
		}
		return fighters;
	}

	/**
	 * 获取活着的单位
	 * @return
	 */
	public List<Fighter> getFightersAlive() {
		return getFightersAlive(false);
	}

	/**
	 * 获取活着的单位（不包括主角）
	 *
	 * @param shuffle 是否打乱顺序
	 * @return
	 */
	public List<Fighter> getFightersAlive(boolean shuffle) {
		List<Fighter> fighters = new ArrayList<>();
		fighters.addAll(getHeroAlive());
		if (shuffle) {
			Collections.shuffle(fighters);
		}
		return fighters;
	}

	/**
	 * 获取友方活着的的单位(不包括主角)
	 * @param fighter
	 * @return
	 */
	public List<Fighter> getFriendsAlive(Fighter fighter) {
		return getFriendsAlive(fighter,false);
	}

	/**
	 * 获取友方活着的的单位
	 * @param fighter
	 * @param shuffle
	 * @return
	 */
	public List<Fighter> getFriendsAlive(Fighter fighter,boolean shuffle){
		List<Fighter> fighters = getFightersAlive().stream().filter(a -> a.getPid() != fighter.getPid()).collect(Collectors.toList());
		if(shuffle){
			Collections.shuffle(fighters);
		}
		return fighters;
	}


	private List<HeroFighter> getHeroAlive(){
		return getHeroAvailable().stream().filter(HeroFighter::isAlive).collect(Collectors.toList());
	}

	/**
	 * 获取死掉的单位（不包括主角）
	 * @return
	 */
	public List<Fighter> getFightersDead(){
		return getFightersDead(true);
	}

	public List<Fighter> getFightersDead(boolean shuffle) {
		List<Fighter> fighters = new ArrayList<>();
		fighters.addAll(getHeroDead());
		if (shuffle) {
			Collections.shuffle(fighters);
		}
		return fighters;
	}

	/**
	 * 获取阵亡的英雄
	 * @return
	 */
	public List<Fighter> getHeroDead(){
		return getHeroAvailable().stream().filter(HeroFighter::isDead).collect(Collectors.toList());
	}

	/**
	 * 获取所有英雄单位
	 * @return
	 */
	@JsonIgnore
	public List<HeroFighter> getAllHero(){
		return heros;
	}


	public FightTeam copy() {
		FightTeam cp = new FightTeam();
		cp.team = this.team;
		cp.hallow = this.hallow == null ? null : hallow.copy();
		cp.deputyHallow = this.deputyHallow == null ? null : deputyHallow.copy();
		cp.heros = ListKit.cloneList(this.heros, HeroFighter::copy);
		cp.pets = MapKit.cloneDeep(this.pets);
		cp.status = this.status == null ? null : status.copy();
		return cp;
	}
}
